﻿#light

type 'a Given    = | Given of (unit -> 'a)
type 'a AndGiven = | AndGiven of ('a -> 'a) list * 'a Given
type 'a When     = | When of ('a -> 'a) * 'a AndGiven
type 'a Then     = | Then of ('a -> 'a) list * 'a When

let given str = AndGiven([], Given str)
let andGiven str (AndGiven (givenList,scenario)) = AndGiven (str :: givenList ,scenario)
let whens str given = When (str, given)
let thens str whens = Then ([str], whens)
let andThens str (Then (thenList,given)) = Then (str::thenList,given)

let endStory (Then (thenList, 
                   When (whenItem, 
                    (AndGiven (givenList, 
                      Given init))))) =

                         (List.fold_left (fun s f -> f s) (init ()) (List.rev givenList) ) 
                          |> whenItem 
                          |> (fun thensInit -> (List.fold_left (fun s f -> f s) thensInit (List.rev thenList)))
                          
